Data processing systems, such as database management systems (DBMSs) commonly operate with multiple buffer pools. Buffer pools are data caches located in volatile memory that are primarily used to store recently accessed data. The purpose of a buffer pool is to permit application data of immediate importance to be quickly accessed by an application from volatile memory, and thereby limit the need to load such data from secondary storage (e.g., a disk or tape drive). There is a disadvantage for incurring associated physical I/O delays of secondary storage. Since accesses to volatile memory can be several orders of magnitude faster than accesses to secondary storage, significant efficiency gains (such as increased speed of program execution) may be achieved through the use of buffer pools.
Data stored in a buffer pool is typically stored in the form of memory pages. As known by those skilled in the art, a memory page is essentially a contiguous block of data as it appears in secondary storage. In most cases, a memory page may include a “header” portion that uniquely identifies the memory page and may include a data portion that may provide application data. The data portion is typically substantially larger than the header portion.
A buffer pool may have sufficient storage capacity to store thousands or even millions of memory pages, with the number of memory pages per buffer pool being configured by the user. To manage these memory pages, a number of data structures are typically maintained. For example, a hash bucket list may be maintained to support efficient storage of, and access to, memory pages within the buffer pool.
In addition, data structures relating to an operative buffer pool memory page victimization scheme may be maintained. Memory page “victimization” (or “eviction”) refers to the removal of a memory page from a buffer pool to provide space for an incoming page, as may be necessary upon the occurrence of a memory page miss (that is, a request for a memory page that is not presently in the buffer pool) when the buffer pool is filled to capacity.
The purpose of known victimization schemes is usually to evict the memory page that is least likely to require reloading into the buffer pool in the future so that future secondary storage physical I/O delays may be minimized. This goal is, of course, difficult to achieve as it entails some degree of prediction of future events that may or may not prove to be accurate.
An example of a victimization scheme is the Least Recently Used (LRU) approach, in which memory pages that have been used least recently are targeted for victimization from the buffer pool in the expectation that pages which have not recently been accessed are least likely to be accessed in the future. In that scheme, an LRU linked list data structure is often maintained for the purpose of organizing the memory pages in chronological order of most recent use.
When a database utilizes multiple buffer pools, the size of each buffer pool may be independently adjustable to permit the pools to be adapted to various applications or data objects. For example, it may be desirable to increase the size of one or more buffer pools used in conjunction with an application that cyclically accesses a finite set of memory pages (e.g., due to a programming loop).
This will ensure that the buffer pool is sufficiently large to be able to contain all of the memory pages accessed during the loop or cycle and may avoid the need to repeatedly load the same memory pages into the buffer pool. Alternatively, if the application scans large data sets in a single pass, the use of a large buffer pool may not be warranted as even a large size may not preclude a significant number of memory page misses. Buffer pool sizes may also be dictated more generally by competing performance and cost concerns. On one hand, large buffer pools may be advantageous in that the frequency of memory page misses may be reduced. On the other hand, smaller buffer pools may be less expensive to implement and may have a higher degree of utilization than a large buffer pool.
One known method of buffer pool size selection is based on a simulation or modeling of the associated application's anticipated memory page access patterns; this simulation is performed prior to run time. In a typical simulation, statistical methods are used to project memory access patterns based on the nature of the application to be executed and the anticipated system load. Memory is then allocated to the buffer pools prior to run-time on the basis of the projected patterns, with a view to minimizing the number of accesses to secondary storage.
An intrinsic flaw of such known methods of buffer pool memory allocation is the fact that actual application behavior may differ from projected behavior due to unforeseen events, such as variable system loads, network delays, unanticipated user behavior or changes in the workload behavior. When unforeseen events occur, the assumptions underlying a particular buffer pool memory allocation may be invalidated. In addition, the performance of the data processing system may disadvantageously suffer because the chosen buffer pool sizes may prove to be ill suited for the data access patterns that actually occur. Moreover, adjustment of buffer pool sizes may necessitate suspension or termination of the executing application.
At least one dynamic memory reallocation scheme has been proposed, according to which a database system has multiple buffer pools with a fixed cumulative capacity in which the user specifies a random access response time goal for each buffer pool prior to run time.
In operation, the buffer pool sizes are automatically expanded or contracted based on the database workload to achieve the response time goals, with the cumulative capacity of the buffer pools remaining constant. Disadvantageously, this approach still requires the user to “set” the desired response times prior to run time. If unforeseen system events occur during operation that cause the system's processor to be loaded in an unanticipated way, the response times set by the user may not actually be representative of desirable or achievable thresholds and system efficiency may suffer.
What is therefore needed is a solution that addresses, at least in part, the above-noted difficulties in allocating or reallocating computer memory among buffer pools to maximize response time and system efficiency. The need for such a system has heretofore remained unsatisfied.